#include <iostream>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

#define PATH "."
#define SDEFAULT -1
#define SIZE 1024
#define PROJID 0X66
#define gmode 0666
#define ERROR_SHOW(msg)     \
	do                      \
	{                       \
		perror(msg);        \
		exit(EXIT_FAILURE); \
	} while (0)

class Shm{
public:
	Shm():_key(SDEFAULT), _shmid(SDEFAULT), _size(SIZE) {}

	void Create(){
		CreateHelp(IPC_CREAT | IPC_EXCL | gmode);
	}

	void Destory(){
		if(_key < 0){
			ERROR_SHOW("ftok error");
		}

		int n = shmctl(_shmid, IPC_RMID, nullptr);
		if(n < 0){
			ERROR_SHOW("shmctl error");
		}
		std::cout << "shmctl success, shm deleted" << std::endl;
	}

	void Get(){
		CreateHelp(IPC_CREAT | gmode);
		if(_shmid < 0){
			ERROR_SHOW("shmget error");
		}
		std::cout << "shmget success, shmid is: " << _shmid << std::endl;
	}

	void* Attach(){
		_shmat = shmat(_shmid, nullptr, 0);
		if(_shmat == (void*)-1){
			ERROR_SHOW("shmat error");
		}
		std::cout << "shmat success, attached to shared memory" << std::endl;

		return _shmat;
	}

	void* VirtualAdd(){
		return Attach();
	}

	~Shm(){}

private:
	void CreateHelp(int mode){
		_key = ftok(PATH, PROJID);
		if(_key < 0){
			ERROR_SHOW("ftok error");
		}
		std::cout<<"key is: " << _key << std::endl;

		_shmid = shmget(_key, _size, mode);
		if(_shmid < 0){
			ERROR_SHOW("shmget error");
		}
		std::cout << "shmget success, shmid is: " << _shmid << std::endl;
	}

	key_t _key;
	int _size;
	int _shmid;
	void* _shmat;
};